﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace HB.Base
{
    /// <summary>
    /// 定时任务调度器
    /// </summary>
    public class TimingTask
    {
        /// <summary>
        /// 具备超时监控的Task
        /// </summary>
        public class OutTimeTask
        {
            Action taskAction;
            Action onTimeCallback;
            Action outTimeCallback;
            Action finallyCallback;
            int miniSecondOfOutTime;
            /// <summary>
            /// 建立超时任务Task
            /// </summary>
            /// <param name="taskAction"></param>
            /// <param name="miniSecondOfOutTime"></param>
            public OutTimeTask(Action taskAction, int miniSecondOfOutTime)
            {
                if (taskAction == null) { throw new Exception("taskAction can not be null"); }
                if (miniSecondOfOutTime < 0) { throw new Exception("miniSecondOfOutTime>0"); }
                this.taskAction = taskAction;
                this.miniSecondOfOutTime = miniSecondOfOutTime;
            }
            /// <summary>
            /// 时间范围内完成任务回调
            /// </summary>
            /// <param name="onTimeCallback"></param>
            /// <returns></returns>
            public OutTimeTask OnFinishOnTime(Action onTimeCallback)
            {
                if (onTimeCallback == null) { throw new Exception("onTimeCallback can not be null"); }
                this.onTimeCallback = onTimeCallback;
                return this;
            }
            /// <summary>
            /// 超时，自动取消任务后回调
            /// </summary>
            /// <param name="outTimeCallback"></param>
            /// <returns></returns>
            public OutTimeTask OnOutTime(Action outTimeCallback)
            {
                if (outTimeCallback == null) { throw new Exception("outTimeCallback can not be null"); }
                this.outTimeCallback = outTimeCallback;
                return this;
            }
            /// <summary>
            /// 最后回调
            /// </summary>
            /// <param name="finallyCallback"></param>
            /// <returns></returns>
            public OutTimeTask OnFinally(Action finallyCallback)
            {
                if (finallyCallback == null) { throw new Exception("finallyCallback can not be null"); }
                this.finallyCallback = finallyCallback;
                return this;
            }
            /// <summary>
            /// 执行调度
            /// </summary>
            public void Run()
            {
                Task.Factory.StartNew(() =>
                {
                    CancellationTokenSource token = new CancellationTokenSource();
                    var temp = Task.Factory.StartNew(taskAction, token.Token);
                    if (temp.Wait(miniSecondOfOutTime))
                    {
                        onTimeCallback.Invoke();
                    }
                    else
                    {
                        token.Cancel();
                        outTimeCallback?.Invoke();
                    }
                    finallyCallback?.Invoke();
                });
            }
        }
        /// <summary>
        /// 基于超时时间的Task
        /// </summary>
        /// <param name="taskAction">执行的委托</param>
        /// <param name="miniSecondOfOutTime">超时时间（ms）</param>
        public static OutTimeTask RunBaseOutTime(Action taskAction, int miniSecondOfOutTime)
        {
            return new OutTimeTask(taskAction, miniSecondOfOutTime);
        }
#if NETSTANDARD || NET45_OR_GREATER
        /// <summary>
        /// 运行简单循环任务
        /// </summary>
        /// <param name="runTimes">运行次数</param>
        /// <param name="interval">运行时间间隔（ms）</param>
        /// <param name="a">委托方法</param>
        /// <param name="runCondition">允许运行条件，如为false，将提前结束</param>
        /// <returns></returns>
        public static Task Run(ushort runTimes, ushort interval, Action a, Func<bool> runCondition)
        {
            if (a == null) { throw new Exception("action can not be null"); }
            return Task.Run(async () =>
           {
               for (int i = 0; i < runTimes; i++)
               {
                   a.Invoke();
                   if (runCondition?.Invoke() == false) { break; }
                   await Task.Delay(interval);
               }
           });
        }

#endif
#if NET40
        /// <summary>
        /// 运行简单循环任务
        /// </summary>
        /// <param name="runTimes">运行次数</param>
        /// <param name="interval">运行时间间隔（ms）</param>
        /// <param name="a">委托方法</param>
        /// <param name="runCondition">允许运行条件，如为false，将提前结束</param>
        /// <returns></returns>
        public static Task Run(ushort runTimes, ushort interval, Action a, Func<bool> runCondition)
        {
            if (a == null) { throw new Exception("action can not be null"); }
            return Task.Factory.StartNew(() =>
        {
            for (int i = 0; i < runTimes; i++)
            {
                a.Invoke();
                if (runCondition?.Invoke() == false) { break; }
                Thread.Sleep(interval);
            }
        });
        }

        

#endif
    }
}
